package com.liao.rent.utils;

/**
 * @Author: ljt
 * @Description: JWT工具类
 * @DateTime: 2024/11/26 上午11:07
 **/


import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.InvalidClaimException;
import com.auth0.jwt.exceptions.JWTCreationException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.auth0.jwt.interfaces.JWTVerifier;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.Calendar;
import java.util.Date;
import java.util.Objects;

/**
 * Jwt工具类
 *
 **/
@Slf4j
@Component
public class JwtUtil {
    /**
     * 签发人
     */
    @Value("${jwt.issuer}")
    private String issuer;
    /**
     * 加密算法
     */
    private Algorithm algorithm;
    /**
     * 秘钥
     */
    @Value("${jwt.secret}")
    private String secret;

    // 私有函数用来指定默认算法器
    private void DefaultAlgorithm(){
        if(Objects.isNull(this.algorithm)){
            this.algorithm = Algorithm.HMAC256(secret);
        }
    }

    public JwtUtil(){
    }

    /**
     * 生成 Token
     * @parm username
     * @return String
     */
    public String generateToken(String username){
        this.DefaultAlgorithm();

        Calendar calendar = Calendar.getInstance();
        Date issuedTime = calendar.getTime();
        // 七天有效期
        calendar.add(Calendar.DAY_OF_YEAR, 7);
        Date expiresTime = calendar.getTime();

        try {
            String token = JWT.create()
                    .withIssuer(issuer)         // 设置发行人
                    .withSubject(username)
                    .withIssuedAt(issuedTime)   // 设置签发时间
                    .withExpiresAt(expiresTime) // 设置过期时间
                    .sign(algorithm);
            return token;
        } catch (JWTCreationException exception){
            // 生成失败会抛出异常
        }
        return null;
    }

    /**
     * 校验Token
     * 校验不成功会抛出JWTVerificationException异常，并返回null
     * @param token
     * @return DecodedJWT
     */
    public DecodedJWT VerifyToken(String token){
        this.DefaultAlgorithm();

        try {
            JWTVerifier verifier = JWT.require(algorithm)
                    .withIssuer(issuer)
                    .build();

            return verifier.verify(token);
        }catch (InvalidClaimException e){
            // 无效的令牌
        } catch (TokenExpiredException e){
            // 令牌过期
        }
        return null;
    }
}
